﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.ComponentModel;
using System.Windows.Forms;
using System.Xml;

using SourceGrid;
using iPdf.Properties;

namespace iPdf
{
    partial class TataGrid
    {
        #region Columns

        public TataGridColumnInfo Id, Source, Destination, From, To, Status;

        private struct TataGridItem
        {
            public string FileName;
            public int RowIndex;

            public TataGridItem(string fileName, int row)
            {
                FileName = fileName;
                RowIndex = row;
            }
        }


        #region Creators

        private void CreatorIDColumn(string item)
        {
            Id[RowsCount - 1] = CreateRowHeader(RowsCount-1);
        }

        private void CreateSourceColumn(string item)
        {
            Source[RowsCount - 1] = CreateFileNameCell(sourceCellTooltip, null, item);
        }

        private void CreateDestinationColumn(string item)
        {
            bool visible = IsColumnVisible(Destination);
            if (visible)
            {
                CreateDestinationCell(RowsCount - 1, GetDestination(item));
            }
        }

        private void CreateFromToColumns(string item)
        {
            bool visible = IsColumnVisible(From);

            if (visible)
            {
                CreateFromToCell(RowsCount - 1, item);
            }
        }

        private void CreateStatusColumn(string item)
        {
            Status[RowsCount - 1] = CreateRegularCell(ItemStatus.Idle.ToString());
        }

        #endregion

        #region Updators

        //Hide/remove/show/update cells
        public void UpdateCells()
        {
            if (Global.MainWindow.Busy)
            {
                EnableAutoSize(false);
                EnableControllerAndEditor(false);
                EnableSorting(false);
                return;
            }

            destinatinCellEditor.Extension = Global.CurrentPage.DestinationFormat.Extension;

            if (SelectionExists && Global.MainWindow.TabPageChanging)
            {
                Selection.ResetSelection(false);
            }

            EnableAutoSize(true);
            EnableControllerAndEditor(true);
            EnableSorting(true);
            
            int removedItemCnt = 0;
            int adjustedIndex;
            int rowsCnt = RowsCount;
            for (int i = 0; i < rowsCnt; ++i)
            {
                adjustedIndex = i - removedItemCnt;
                foreach (TataGridColumnInfo colHead in Columns)
                {
                    if (!colHead.Update(adjustedIndex))
                    {
                        ++removedItemCnt;
                        break;
                    }
                }
            }

            AutoSizeCells();

            //cause the height of the rows could be changed, 
            //we need to reset the height of the rows
            for (int i = 1; i < RowsCount; ++i)
            {
                Rows[i].Height = gridRowHeight;
            }

            PerformLayout();

            Helper.CollectGarbage();
        }

        private bool UpdateIDColumn(int row)
        {
            if (row == 0)
            {
                return true;
            }
            Id.SetValueAt(row, row);

            return true;
        }

        private bool UpdateSourceColumn(int row)
        {
            if (row > 0 && Global.MainWindow.TabPageChanging && 
                Global.MainWindow.PreviousPage != null)
            {
                FileFormat format = Global.MainWindow.Format;
                string oriSrc = (string)Source.GetValueAt(row);
                string oriDest = (string)Destination.GetValueAt(row);
                if (!format.IsOneOf(oriSrc))
                {
                    if (oriDest != null && format.IsOneOf(oriDest) && File.Exists(oriDest))
                    {
                        Source.SetValueAt(row, oriDest);
                    }
                    else
                    {
                        RemoveRow(row);
                        return false;
                    }
                }
            }

            return true;
        }

        private bool UpdateDestinationColumn(int row)
        {
            bool visible = IsColumnVisible(Destination);
            if (row == 0)
            {
                Destination.Visible = visible;
            }

            if (row > 0 && Global.MainWindow.TabPageChanging && visible)
            {
                string sourceFileName = (string)Source.GetValueAt(row);
                string destFileName = GetDestination(sourceFileName);

                if (Destination.ExistsAt(row))
                {
                    Destination.SetValueAt(row, destFileName);
                }
                else
                {
                    CreateDestinationCell(row, destFileName);
                }
            }

            return true;
        }

        private bool UpdateFromToColumn(int row)
        {
            bool visible = IsColumnVisible(From);
            if (row == 0)
            {
                From.Visible = visible;
                To.Visible = visible;
                return true;
            }

            if (row > 0 && Global.MainWindow.TabPageChanging && visible)
            {
                CreateFromToCell(row, (string)Source.GetValueAt(row));
            }

            return true;
        }


        private bool UpdateStatusColumn(int row)
        {
            if (row > 0 && Global.MainWindow.TabPageChanging)
            {
                Status.SetValueAt(row,  ItemStatus.Idle.ToString());
            }

            return true;
        }

        #endregion

        #region Helper methods

        protected override void InitializeColumns()
        {
            Id = CreateColumn(MinTataColumnWidth, Resources.IdColumnName, 
                Resources.IdColumnDescription, false);
            Source = CreateColumn(0, Resources.SourceColumnName, 
                Resources.SourceColumnDescription);
            Destination = CreateColumn(0, Resources.DestinationColumnName, 
                Resources.DestinationColumnDescription);
            From = CreateColumn(MinTataColumnWidth, Resources.FromColumnName,
                Resources.FromColumnDescription);
            To = CreateColumn(MinTataColumnWidth, Resources.ToColumnName,
                Resources.ToColumnDescription);
            Status = CreateColumn(MinTataColumnWidth, Resources.StatusColumnName,
                Resources.StatusColumnDescription);
        }

        private delegate void FromToCellsUpdator(TataGridItem item, int numOfPages);

        private void UpdateFromToCells(TataGridItem item, int numOfPages)
        {
            lock (this)
            {
                while (true)
                {
                    string itemFileName = (string)Source.GetValueAt(item.RowIndex);
                    if (itemFileName == item.FileName)
                    {
                        //matched, then we update from/to cells
                        SourceGrid.Cells.Cell fromCell = From[item.RowIndex];
                        SourceGrid.Cells.Cell toCell = To[item.RowIndex];

                        if (numOfPages > 0)
                        {
                            //create editor
                            SourceGrid.Cells.Editors.NumericUpDown numericUpDownEditor = new
                                                SourceGrid.Cells.Editors.NumericUpDown(typeof(int), numOfPages, 1, 1);
                            numericUpDownEditor.EditableMode = EditableMode.SingleClick;
                            numericUpDownEditor.UseCellViewProperties = false;
                            numericUpDownEditor.Control.Font = editorFont;

                            //update cells
                            if ((int)fromCell.Value == 0)
                            {
                                fromCell.Value = 1;
                            }
                            fromCell.Editor = numericUpDownEditor;

                            if ((int)toCell.Value == 0)
                            {
                                toCell.Value = numOfPages;
                            }
                            toCell.Editor = numericUpDownEditor;
                        }
                        else
                        {
                            fromCell.Value = toCell.Value = 0;

                            string errorMsg = Resources.InvalidFileItemsTip;
                            errorMsg = errorMsg.Replace("{file}", Path.GetFileName(itemFileName));
                            Global.ShowNotification( errorMsg );
                            //select to highlight the row to show the user that it's invalid
                            Selection.SelectRow(item.RowIndex, true);
                        }

                        return;
                    }
                }
            }
        }

        private void CalculateNumberOfPagesAndUpdateCells(object sender, DoWorkEventArgs e)
        {
            TataGridItem item = (TataGridItem)e.Argument;

            int numOfPages = Global.CurrentPage.GetNumberOfPagesOfSourceFile(item.FileName);

            if (this.InvokeRequired)
            {
                object[] paras = new object[2] { item, numOfPages };
                Invoke(new FromToCellsUpdator(UpdateFromToCells), paras);
            }
            else
            {
                UpdateFromToCells(item, numOfPages);
            }
        }

        private void CreateFromToCell(int row, string item)
        {
            SourceGrid.Cells.Cell fromCell = CreateRegularCell(0);
            SourceGrid.Cells.Cell toCell = CreateRegularCell(0);
            From[row] = fromCell;
            To[row] = toCell;

            if (row > 1)
            {
                string prevItem = (string)Source.GetValueAt(row - 1);
                if (prevItem == item)
                {
                    SourceGrid.Cells.Cell prevFromCell = From[row - 1];
                    SourceGrid.Cells.Cell prevToCell = To[row - 1];

                    if (prevFromCell != null && prevToCell != null)
                    {
                        SourceGrid.Cells.Editors.NumericUpDown editor =
                            (SourceGrid.Cells.Editors.NumericUpDown)prevFromCell.Editor;
                        if (editor != null)
                        {
                            fromCell.Editor = toCell.Editor = editor;
                            int numberOfPages = (int)editor.Control.Maximum;
                            int from = (int)prevFromCell.Value;
                            int to = (int)prevToCell.Value;
                            if (from > to)
                            {
                                int tmp = from;
                                from = to;
                                to = tmp;
                            }

                            if (to < numberOfPages)
                            {
                                fromCell.Value = to + 1;
                            }
                            else
                            {
                                fromCell.Value = 1;
                            }

                            toCell.Value = numberOfPages;

                            return;
                        }
                    }
                }
            }

            BackgroundWorker worker = new BackgroundWorker();
            worker.DoWork += new DoWorkEventHandler(CalculateNumberOfPagesAndUpdateCells);

            worker.RunWorkerAsync(new TataGridItem(item, row));
        }

        private static string GetDestination(string item, string directory)
        {
            return Global.CurrentPage.GetDestination(item, directory);
        }

        private static string GetDestination(string item)
        {
            return GetDestination(item, string.Empty);
        }

        private static bool IsColumnVisible(TataGridColumnInfo colInfo)
        {
            return Global.CurrentPage.IsColumnVisible(colInfo);
        }

        private void InstallColumnCreatorAndUpdator()
        {
            Id.Creator = CreatorIDColumn;
            Id.Updator = UpdateIDColumn;
            Source.Creator = CreateSourceColumn;
            Source.Updator = UpdateSourceColumn;
            Destination.Creator = CreateDestinationColumn;
            Destination.Updator = UpdateDestinationColumn;
            From.Creator = CreateFromToColumns;
            From.Updator = UpdateFromToColumn;
            Status.Creator = CreateStatusColumn;
            Status.Updator = UpdateStatusColumn;
        }

        private void CreateDestinationCell(int row, string item)
        {
            Destination[row] = CreateFileNameCell(destinationCellTooltip, destinatinCellEditor, item); ;
        }
        #endregion

        #endregion
    }
}
